package com.example.smartvillage.onenet;

import android.os.Handler;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

import java.io.IOException;
import java.util.concurrent.Executor;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MyOneNetApi {

    //自定义的OneNetApi实现
    private static final String TAG = "我的OneNetApi客户端";

    private final Handler resultHandler;
    private final Executor executor;
    private final OneNetApi oneNetApi;

    public MyOneNetApi(Executor executor, Handler resultHandler) {
        this.executor = executor;
        this.resultHandler = resultHandler;

        //自定义请求拦截器，用于添加通用的参数，如安全鉴权等
        CommonInterceptor commonInterceptor = new CommonInterceptor();

        //将自定义请求拦截器添加到一个新的OkHttp客户端
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(commonInterceptor)
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.heclouds.com/")//基础URL
                .client(client)//替换掉默认的OkHttp客户端
                .addConverterFactory(GsonConverterFactory.create()) //添加ScalarsConverterFactory，将返回的数据转化为字符串，
                // 使用GsonConverterFactory，则可转化为Gson
                .build();

        this.oneNetApi = retrofit.create(OneNetApi.class);//实例化
    }

    /**
     * 发送命令
     *
     * @param qos 是否需要设备应答，默认为0。
     * 0：最多发送一次，不关心设备是否响应
     * 1：至少发送一次，如果设备收到命令后没有应答，则会在下一次设备登录时若命令在有效期内（有效期定义参见timeout参数）则会重发该命令
     * @param timeout 命令有效时间，默认0。
     * 0：在线命令，若设备在线,下发给设备，若设备离线，直接丢弃
     * >0： 离线命令，若设备在线，下发给设备，若设备离线，在当前时间加timeout时间内为有效期，有效期内，若设备上线，则下发给设备
     * 单位：秒
     * 有效范围：0~2678400
     * @param command 发送的命令
     * @param callback 回调方法
     *
     */
    public void sendCommand(int qos, int timeout, String command, Callback<JsonObject> callback){

        RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), command);
        Call<JsonObject> call = oneNetApi.SendCommand(qos, timeout, requestBody);//实例化请求对象

        executor.execute(() -> {
            try {
                Response<JsonObject> response = call.execute();//实际的网络请求
                Log.d(TAG, "发送命令：返回的信息"+response.body());
                notifyResult(response, callback);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 发送实时命令
     *
     * @param command 发送的命令
     * @param callback 回调方法
     *
     */
    public void sendCommand(String command, Callback<JsonObject> callback){

        RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), command);
        Call<JsonObject> call = oneNetApi.SendCommand(0, 0, requestBody);//实例化请求对象

        executor.execute(() -> {
            try {
                Response<JsonObject> response = call.execute();//实际的网络请求
                Log.d(TAG, "发送命令：返回的信息"+response.body());
                notifyResult(response, callback);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 新增数据点（因为省略了时间，所以时间为当前时间）
     *
     * @param datastream_id 数据流的名称，例如：绿色LED, 湿度, 蜂鸣器
     * @param value 数据流的属性
     * @param callback 回调方法
     *
     */
    public void setDataPoint(String datastream_id, String value, Callback<JsonObject> callback){

        DataStreams dataStreams = new DataStreams(datastream_id, value);
        String requestBody = new Gson().toJson(dataStreams);

        Call<JsonObject> call = oneNetApi.UpdateDataStream(requestBody);//实例化请求对象

        executor.execute(() -> {
            try {
                Response<JsonObject> response = call.execute();//实际的网络请求
                Log.d(TAG, "新增数据点：返回的信息"+response.body());
                notifyResult(response, callback);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }


    /**
     * 查询某一组数据流的当前属性
     *
     * @param datastream_ids 数据流id(即名称)，多个id之间用逗号分开，缺省时为查询所有数据流
     * @param callback 回调方法
     *
     */
    public void getDataStreams(String datastream_ids, final Callback<JsonObject> callback) {

        Call<JsonObject> call = oneNetApi.BatchQueryDataStream(datastream_ids);

        executor.execute(() -> {
            try {
                Response<JsonObject> response = call.execute();//实际的网络请求
                Log.d(TAG, "批量查询数据流信息：返回的信息"+response.body());
                notifyResult(response, callback);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    public interface Callback<T> {
        /**
         * @param response Api调用结果
         */
        void onComplete(Response<T> response);
    }

    private void notifyResult(final Response<JsonObject> response, final Callback<JsonObject> callback) {
        resultHandler.post(() -> callback.onComplete(response));
    }
}
